package cn.amaake.magicplugin.nacos.util;

import com.alibaba.nacos.api.config.ConfigType;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.moandjiezana.toml.Toml;
import org.jsoup.Jsoup;
import org.yaml.snakeyaml.Yaml;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Properties;

public class ConfigParserUtils {
    private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
    private static final Yaml YAML_PARSER = new Yaml();

    /**
     * 解析配置字符串为 Properties 对象
     * @param content 配置内容
     * @param type    配置类型
     * @return Properties 对象
     */
    public static Properties parse(String content, ConfigType type) {
        switch (type) {
            case PROPERTIES:
                return parseProperties(content);
            case XML:
                return parseXml(content);
            case JSON:
                return parseJson(content);
            case TEXT:
                return parseText(content);
            case HTML:
                return parseHtml(content);
            case YAML:
                return parseYaml(content);
            case TOML:
                return parseToml(content);
            case UNSET:
                throw new IllegalArgumentException("未指定配置类型");
            default:
                throw new UnsupportedOperationException("暂不支持此格式: " + type);
        }
    }

    // ==================== 具体解析方法 ====================

    // 解析 Properties 格式
    private static Properties parseProperties(String content) {
        Properties props = new Properties();
        try (StringReader reader = new StringReader(content)) {
            props.load(reader);
        } catch (Exception e) {
            throw new RuntimeException("解析 Properties 失败", e);
        }
        return props;
    }

    // 解析 XML 格式（需符合 JDK 的 XML 属性格式规范）标准化xml
    private static Properties parseXml(String content) {
        Properties props = new Properties();
        try (InputStream inputStream = new ByteArrayInputStream(
                content.getBytes(StandardCharsets.UTF_8))) { // 指定编码
            props.loadFromXML(inputStream); // 加载 XML
            return props;
        } catch (Exception e) {
            throw new RuntimeException("解析 XML 失败", e);
        }
    }

    // 解析 XML 格式（需符合 JDK 的 XML 属性格式规范） 非标准化xml
    public static Properties parseCustomXml(String xmlContent) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            org.w3c.dom.Document doc = builder.parse(new ByteArrayInputStream(xmlContent.getBytes()));

            Properties props = new Properties();
            org.w3c.dom.NodeList entries = doc.getElementsByTagName("entry"); // 按标签名查找

            for (int i = 0; i < entries.getLength(); i++) {
                org.w3c.dom.Element entry = (org.w3c.dom.Element) entries.item(i);
                String key = entry.getAttribute("key"); // 获取属性
                String value = entry.getTextContent();   // 获取文本
                props.setProperty(key, value);
            }
            return props;
        } catch (Exception e) {
            throw new RuntimeException("解析 XML 失败", e);
        }
    }

    // 解析 JSON 格式（扁平化键值对）
    private static Properties parseJson(String content) {
        try {
            Map<String, Object> map = JSON_MAPPER.readValue(content, new TypeReference<Map<String, Object>>() {});
            Properties props = new Properties();
            props.putAll(map);
            return props;
        } catch (Exception e) {
            throw new RuntimeException("解析 JSON 失败", e);
        }
    }

    // 解析纯文本（假设为 key=value 格式）
    private static Properties parseText(String content) {
        Properties props = new Properties();
        String[] lines = content.split("\n");
        for (String line : lines) {
            String[] parts = line.split("=", 2);
            if (parts.length == 2) {
                props.setProperty(parts[0].trim(), parts[1].trim());
            }
        }
        return props;
    }

    // 解析 HTML（提取特定标签内容，例如 <meta> 标签）
    private static Properties parseHtml(String content) {
        Properties props = new Properties();
        try {
            org.jsoup.nodes.Document doc = Jsoup.parse(content);
            // 示例：提取所有 meta 标签的 name 和 content
            doc.select("meta").forEach(element -> {
                String name = element.attr("name");
                String value = element.attr("content");
                if (!name.isEmpty() && !value.isEmpty()) {
                    props.setProperty(name, value);
                }
            });
            return props;
        } catch (Exception e) {
            throw new RuntimeException("解析 HTML 失败", e);
        }
    }

    // 解析 YAML 格式
    private static Properties parseYaml(String content) {
        try {
            Map<String, Object> map = YAML_PARSER.load(content);
            Properties props = new Properties();
            flattenMap("", map, props);
            return props;
        } catch (Exception e) {
            throw new RuntimeException("解析 YAML 失败", e);
        }
    }

    // 解析 TOML 格式
    private static Properties parseToml(String content) {
        try {
            Toml toml = new Toml().read(content);
            Map<String, Object> map = toml.toMap();
            Properties props = new Properties();
            flattenMap("", map, props);
            return props;
        } catch (Exception e) {
            throw new RuntimeException("解析 TOML 失败", e);
        }
    }

    // ==================== 工具方法 ====================

    // 递归展平嵌套 Map（处理 YAML/TOML 嵌套结构）
    private static void flattenMap(String prefix, Map<String, Object> map, Properties props) {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String key = prefix.isEmpty() ? entry.getKey() : prefix + "." + entry.getKey();
            Object value = entry.getValue();
            if (value instanceof Map) {
                flattenMap(key, (Map<String, Object>) value, props);
            } else {
                props.setProperty(key, value.toString());
            }
        }
    }

    public static ConfigType ConfigType(String type) {
        switch (type) {
            case "properties":
                return ConfigType.PROPERTIES;
            case "xml":
                return ConfigType.XML;
            case "json":
                return ConfigType.JSON;
            case "text":
                return ConfigType.TEXT;
            case "html":
                return ConfigType.HTML;
            case "yaml":
                return ConfigType.YAML;
            case "toml":
                return ConfigType.TOML;
            case "unset":
                return ConfigType.UNSET;
        }
        return ConfigType.PROPERTIES;
    }
}
